import os
from flask import Blueprint, request, render_template, jsonify, current_app,send_file,Response
from applications.common import curd
from applications.common.curd import enable_status, disable_status
from applications.common.utils.http import fail_api, success_api, table_api
from applications.common.utils.rights import authorize
from sqlalchemy import text  # 导入 text 函数
from flask_login import current_user
from applications.common.curd import model_to_dicts
from applications.common.helper import ModelFilter
from applications.common.utils.validate import str_escape
from applications.extensions import db
from applications.models import Role, Dept
from applications.models import User, AdminLog
from applications.models import Settings_web
from applications.schemas import Settings_webOutSchema
from applications.common.utils.http import str_to_json
from datetime import datetime
import requests
from requests.exceptions import Timeout
import socket
import ipaddress
import io

bp = Blueprint('api', __name__, url_prefix='/api')
# 设置超时时间
TIMEOUT = 3  # 秒

#  API-WEB
@bp.get('/')
def main():
    # nav_menu = websettings(key_name='Site_Menu',dbName='admin_setings_web')
    nav_menu = Settings_web.query.filter(Settings_web.key_name == 'Site_Menu').first()
    # 数据格式化处理
    nav_menu = Settings_webOutSchema().dump(nav_menu).get('value_name')
    
    return render_template('/system/api/main.html',user=current_user,nav_menu=str_to_json(nav_menu),navtitle='API')

# API-列表
@bp.get('/v1/list')
def list():
    api_list = [
        {'id':1,'name': '每日必应壁纸', 'url': '/api/v1/bing','method': 'GET','params': '无','desc': '获取每日必应壁纸','return': 'image'},   
        {'id':2,'name': '每日必应壁纸', 'url': '/api/v1/bing/image','method': 'GET','params': '无','desc': '获取每日必应壁纸','return': 'json'}, 
        {'id':3,'name':'随机壁纸','url':'/api/v1/bing/random','method':'GET','params':'无','desc':'获取随机壁纸','return':'image'},
        {'id':4,'name':'EPG信息','url':'/epg/get_epg_url','method':'GET','params':'id/ch','desc':'频道节目列表','return':'json'},
        # {'id':5,'name':'EPG_tvsou','url':'/epg/get_epg_tvsou','method':'GET','params':'id/ch','desc':'央视、卫视频道节目列表,每日凌晨1点更新','return':'json'},
        # {'id':6,'name':'EPG_tvmao','url':'/epg/get_epg_tvmao','method':'GET','params':'id/ch','desc':'央视、卫视频道节目列表,每日凌晨1点更新','return':'json'},
        # {'id':99,'name': 'IP', 'url': '/api/v1/ip','method': 'GET','params': 'ip','desc': '根据IP获取地理位置信息'},
    ]
    return jsonify({'code': 200, 'msg': '成功', 'data': api_list})


#### Start API-IP ####
# api/v1/ip接口
@bp.route('/v1/ip', methods=['GET', 'POST'])
def ip():
    ip = request.args.get('ip')
    if ip:
        return jsonify(get_ip_location(ip))
    else:
        # 获取当前请求的IP地址
        ip= request.headers.get('X-Forwarded-For') or request.remote_addr
        return jsonify(get_ip_location(ip))
        # return jsonify({'status': 'error', 'message': 'IP address is required.'})
   
# 获取IP地址信息
def get_ip_location(ip="myip"):
    data = {}
    ip_info_1 = {}
    ip_info_2 = {} 
    try:
        if ip == "myip":
            ip = request.headers.get('X-Forwarded-For') or request.remote_addr
        if is_private_ip(ip):
            return {"status": "error","data": {"country": "","region": "","city": "本地","isp": "局域网","ip": ip,"position": "",}}
        if ip.count('.') == 3 or ip.count(':') == 7:  # ipv4 or ipv6
            ip_info_1 = get_ip_api(ip)
            
        else:
            ip = get_ip_address(ip)
            ip_info_1 = get_ip_api(ip)
            

        if ip_info_1['status'] == 'success' and ip_info_2['status'] == 'success':
            data = {
                "status": "success",
                "data": {
                    "country": ip_info_2['data']['country'],
                    "region": ip_info_2['data']['region'],
                    "city": ip_info_2['data']['city'],
                    "isp": ip_info_1['data']['isp'],
                    "ip": ip_info_2['data']['ip'],
                    "position": ip_info_2['data']['position'],
                }
            }
            return data
        elif ip_info_2['status'] == 'success':
            return ip_info_1
        elif ip_info_1['status'] == 'success':
            return ip_info_2
    except Timeout:
        return {"status": "error", "message": "Connection timed out while trying to fetch IP information.", "data": ""}

# 获取域名IP地址
def get_ip_address(domain):
    try:
        ip_address = socket.gethostbyname(domain)
        return ip_address
    except socket.gaierror as e:
        print(f"Error resolving domain: {e}")
        return None
    
# 调用腾讯位置API获取IP地址信息
def get_qq_location(ip):
    import hashlib
    key = "2LBBZ-EZWLZ-XXXXX-XXXXX-XXXXX-XXXXX"
    sk = "YMamOXXXXXBOGVrwow8JCbXXXXXFdUug"
    
    md5 = hashlib.md5()
    md5.update((f"/ws/location/v1/ip?ip={ip}&key={key}{sk}").encode("utf-8"))
    sig = md5.hexdigest()
    url = f"https://apis.map.qq.com/ws/location/v1/ip?key={key}&ip={ip}&sig={sig}"
    
    try:
        response = requests.get(url, timeout=TIMEOUT)
        data = response.json()
        if data['status'] == 0:
            lat = data['result']['location']['lat']
            lng = data['result']['location']['lng']
            return {
                "status": "success",
                "data": {
                    "country": data['result']['ad_info']['nation'],
                    "region": data['result']['ad_info']['province'],
                    "city": f"{data['result']['ad_info']['city']}{data['result']['ad_info']['district']}",
                    "isp": "Unknown",
                    "ip": data['result']['ip'],
                    "position": f'{lat},{lng}',
                }
            }
        else:
            return {
                "status": "error",
                "data": {
                    "country": "Unknown",
                    "region": "Unknown",
                    "city": "Unknown",
                    "isp": "Unknown",
                    "ip": ip,
                    "position": "",
                }
            }
    except requests.exceptions.RequestException as e:
        return {"status": "error", "message": f"An error occurred: {e}", "data": ""}

# 调用ip-api.com获取IP地址信息
def get_ip_api(ip):
    url = f"http://ip-api.com/json/?ip={ip}&lang=zh-CN"
    
    try:
        response = requests.get(url, timeout=TIMEOUT)
        data = response.json()
        lat = data['lat']
        lng = data['lon']
        if data['status'] == 'success':
            return {
                "status": "success",
                "data": {
                    "country": data['country'],
                    "region": data['regionName'],
                    "city": data['city'],
                    "isp": data['isp'],
                    "ip": data['query'],
                    "position": f'{lat},{lng}',
                }
            }
        else:
            return {
                "status": "error",
                "data": {
                    "country": "Unknown",
                    "region": "Unknown",
                    "city": "Unknown",
                    "isp": "Unknown",
                    "ip": ip,
                    "position": "",
                }
            }
    except requests.exceptions.RequestException as e:
        return {"status": "error", "message": f"An error occurred: {e}", "data": ""}

# 判断IP地址是否为内网IP地址
def is_private_ip(ip):
    private = ipaddress.ip_address(ip).is_private
    if private:
        data = {
                "status": "error",
                "data": {
                    "country": "",
                    "region": "",
                    "city": "本地",
                    "isp": "局域网",
                    "ip": ip,
                    "position": "",
                }
            }
        return True
    else:
        return False
#### End API-IP ####

#### Start bing wallpaper ####
def get_bing():
    base_url = "https://www.bing.com"
    endpoint = "/HPImageArchive.aspx"
    params = {
        'format': 'js',
        'idx': '0',
        'n': '1',
        'mkt': 'en-US'
    }
    response = requests.get(base_url + endpoint, params=params)
    if response.status_code == 200:
        data = response.json()
        if 'images' in data and len(data['images']) > 0:
            image = data['images'][0]
            image_url = base_url + image['url']
            return {
                'title': image['title'],
                'url': image_url,
                'copyright': image.get('copyright', 'No copyright info')
            }
        else:
            return {'error': 'No image found'}
    else:
        return {'error': f'Failed to fetch image, status code: {response.status_code}'}

def save_image(image_url, save_path):
    try:
        response = requests.get(image_url, stream=True)
        if response.status_code == 200:
            with open(save_path, 'wb') as file:
                for chunk in response.iter_content(chunk_size=8192):
                    file.write(chunk)
            return {'success': True, 'message': f'Image saved to {save_path}'}
        else:
            return {'success': False, 'message': f'Failed to download image, status code: {response.status_code}'}
    except Exception as e:
        return {'success': False, 'message': str(e)}

@bp.get('/v1/bing')
def bing_wallpaper():
    bing_image = get_bing()
    if 'url' in bing_image:
        image_url = bing_image['url']
        response = requests.get(image_url)
        if response.status_code == 200:
            # Create a BytesIO stream from the image content
            img_stream = io.BytesIO(response.content)
            return Response(img_stream, mimetype='image/jpeg')
        else:
            return jsonify({'error': f'Failed to download image, status code: {response.status_code}'})
    else:
        return jsonify(bing_image)
    
def Task_bing_wallpaper():
    bing_image = get_bing()
    if 'url' in bing_image:
        date = datetime.now().strftime("%Y%m%d")
        image_url = bing_image['url']
        image_title = bing_image['title']
        file_name = f"{date}_{image_title}.jpg".replace(":", "_").replace("/", "_")
        save_directory = "static/upload/bing"  # 保存路径
        save_path = os.path.join(save_directory, file_name)
        # 确保保存目录存在
        os.makedirs(save_directory, exist_ok=True)
        save_image(image_url, save_path)

# 每日获取bing壁纸-图片api-json
@bp.route('/v1/bing/image', methods=['GET'])
def get_bing_image():
    # 参数
    return jsonify({'code': 200, 'message': 'success', 'data': get_bing()})

import random
# 获取目录下随机图片
@bp.route('/v1/bing/random', methods=['GET'])
def get_random_image():
    save_directory = "static/upload/bing"  # 保存路径
    files = os.listdir(save_directory)
    # 排除非图片格式文件
    files = [file for file in files if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp'))]
    if files:
        random_file = random.choice(files)
        file_path = os.path.join(save_directory, random_file)
        
        # Directly pass the file path to send_file
        return send_file(
            file_path,
            # 支持多种图片格式
            mimetype='image/jpeg'
        )
    else:
        return jsonify({'code': 404, 'message': 'No images found in the directory.'}), 404


#### End bing wallpaper ####